home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Programmer Power Tools
/
Programmer Power Tools.iso
/
filedocs
/
simraz13.arc
/
SIMRAZOR.PAS
< prev
Wrap
Pascal/Delphi Source File
|
1989-12-18
|
15KB
|
354 lines
Program simrazor;
{ Shortens a MailMerge export of a SimIBM database index file by removing }
{ unwanted fields, or parts thereof. }
{ Optionally, merges multiple input files. }
{ Specify parameters on command line; call without parameters for help. }
{ FreeWare by TapirSoft Gisbert W.Selke, Dec 89 }
{ This programme comes as is; no guarantees whatsoever! }
{ Compiled under MS DOS 3.3, using TurboPascal 5.5 }
{ DEFINE DEBUG } { $DEFINE while debugging }
{$A+,B-,D+,E+,F-,I-,L+,N-,O-,V-}
{$IFDEF DEBUG }
{$R+,S+ }
{$ELSE }
{$R-,S- }
{$ENDIF }
{$M 65520,0,400000 }
Const progname = 'SIMRAZOR';
version = '1.3';
copyright = 'FreeWare (c) TapirSoft Gisbert W.Selke, Dec 89';
bufsize = 64000;
maxlength = 50; { maximum field length in input files }
maxinfields = 10; { number of fields in input files }
maxinfiles = 5; { maximum number of input files }
maxoutfields = 15; { max number of output fields }
fieldnum : Array [1..maxinfields] Of boolean =
(False,False,False,True,True,True,True,False,False,False);
{ False = ASCII; True = numeric }
Type buffer = Array [1..bufsize] Of byte; { i/o buffer }
bufptr = ^buffer;
name = string[80]; { file name }
tentry = string[maxlength]; { single field }
entry = Array [1..maxinfields] Of tentry;{ input record }
extry = Array [1..maxoutfields] Of tentry;{ output record }
Var fout : text; { output file }
outname : name; { name of output file }
outbufptr: bufptr; { output buffer }
fin : Array [1..maxinfiles] Of text; { input files }
inname : Array [1..maxinfiles] Of name; { names of input files }
inbufptr : Array [1..maxinfiles] Of bufptr;{ input buffers }
e : Array [1..maxinfiles] Of extry; { current input records }
eoff : Array [1..maxinfiles] Of boolean;{ input eof flags }
ctout : longint; { count of output records }
ctin : Array [1..maxinfiles] Of longint;{ counts of input records }
outfld : Array [1..maxoutfields] Of byte;{ pointers to output fields }
outlen : Array [1..maxoutfields] Of integer;{ lengths of output fields }
ninfiles : byte; { number of input files }
noutfields : byte; { number of output fields }
choose : byte; { pointer to record for output}
nopen : byte; { number of open input files }
i : byte;
Function ReadKey : Char;
{ read a char from StdIn without echoing; don't need CRT unit for this! }
Inline($B4/$07/ {Mov ah, 7}
$CD/$21); {Int $21}
Function yesnoq : boolean;
{ get a yes-or-no answer }
Var ch : char;
Begin { yesnoq }
Repeat
ch := UpCase(ReadKey);
Until ch In ['Y','J','1','N','0'];
writeln(ch);
yesnoq := ch In ['Y','J','1'];
End; { yesnoq }
Procedure abort(errmsg : string; code : byte);
{ abort with error message }
Begin { abort }
writeln;
writeln(errmsg);
Halt(code);
End; { abort }
Procedure usage;
{ show usage info and die }
Begin { usage }
writeln('Shorten a SimIBM index file by removing unwanted fields.');
writeln('Optionally merge sorted files.');
writeln;
writeln('This programme may be used and copied freely,');
writeln('but it comes with no guarantees whatsoever.');
writeln;
writeln('Usage: SIMRAZOR /F<field>... /I<inname>... /O<outname>');
writeln(' where <field> is one of A..J, optionally followed by');
writeln(' a maximum field length (negative length to start from');
writeln(' the right) (up to ',maxoutfields,' /F options allowed),');
writeln(' <inname> is an input file name (up to ',maxinfiles,
' allowed),');
writeln(' and <outname> is the output file name.');
writeln(' (Default extension for files: IDX)');
writeln(' A = disk; B = directory; C = file name; D = version;');
writeln(' E = size; F = type; G = date; H = description;');
writeln(' I = first part of dir; J = second part of directory.');
writeln;
writeln('Example:');
writeln('SIMRAZOR /FI-1 /FJ11 /FC /FE6 /FG /FH /ISIMIBM.IDX ',
'/OSIMSHORT.IDX');
Halt(1);
End; { usage }
Procedure getoneline(Var f : text; Var fieldout : extry);
{ get one line and clean it up }
Var i, k, nf, len : byte;
exquote : boolean;
lin : string;
fields : entry;
Procedure cleanse;
{ perform the cleaning }
Var i, k, l : byte;
isquote : boolean;
Begin { cleanse }
For i := 1 To noutfields Do
Begin { check all fields to be output }
k := outfld[i];
fieldout[i] := fields[k];
If k = 9 Then
Begin { special check for part 1 of dir field: maybe add a blank }
If fieldout[i] = 'MSDOS' Then fieldout[i] := 'MSDOS ';
End;
l := Length(fieldout[i]);
If l >= 2 Then
Begin { quoted field }
isquote := (fieldout[i][1] = '"') And (fieldout[i][l] = '"');
If isquote Then
Begin
fieldout[i] := Copy(fieldout[i],2,l-2);
l := l - 2;
End;
End
Else isquote := False;
If l > Abs(outlen[i]) Then
Begin { input field too long }
If fieldnum[k] Then
Begin { numeric field }
fieldout[i] := '';
For l := 1 To outlen[i] Do fieldout[i] := fieldout[i] + '9';
End
Else
Begin { ASCII field }
If outlen[i] >= 0 Then Delete(fieldout[i],Succ(outlen[i]),255)
Else Delete(fieldout[i],1,l+outlen[i]);
End;
End;
If isquote Then fieldout[i] := '"' + fieldout[i] + '"';
End;
End; { cleanse }
Begin { getoneline }
readln(f,lin);
len := Length(lin);
For i := 1 To maxinfields Do fields[i] := '';
nf := 0;
i := 1;
exquote := True;
While (nf < maxinfields) And (i < len) Do
Begin
k := i;
Repeat
If lin[i] = '"' Then exquote := Not exquote;
Inc(i);
Until (i > len) Or ((lin[i] = ',') And exquote);
Inc(nf);
fields[nf] := Copy(lin,k,i-k);
Inc(i);
End;
i := Pos('.',fields[2]);
fields[Pred(maxinfields)] := Copy(fields[2],2,i-2); { part 1 of dir }
If (fields[2] <> '') And (fields[2][1] = '"') Then
Delete(fields[Pred(maxinfields)],1,1);
fields[maxinfields] := Copy(fields[2],Succ(i),Length(fields[2])-i-1);
If (fields[2] <> '') And { part 2 of dir }
(fields[2][Length(fields[2])] = '"') Then
Delete(fields[maxinfields],Length(fields[maxinfields]),1);
cleanse;
End; { getoneline }
Procedure getnextline;
{ get next line from input file(s) }
Var i, k : byte;
Begin { getnextline }
For i := 1 To ninfiles Do
Begin { read input lines, where necessary and possible }
If (e[i,1] = '') And (Not eoff[i]) Then
Begin
getoneline(fin[i],e[i]);
If IOResult <> 0 Then abort('Error reading from ' + inname[i] +
' - abort!',31);
Inc(ctin[i]);
eoff[i] := EoF(fin[i]);
If eoff[i] Then Dec(nopen);
End;
End;
choose := 1;
For i := 2 To ninfiles Do
Begin { find out which of the input record to take next }
If e[i,1] <> '' Then
Begin { non-empty record }
k := 0;
While k < noutfields Do
Begin { scan fields in output order }
Inc(k);
If e[choose,k] < e[i,k] Then k := noutfields { old guess was better }
Else
Begin
If e[choose,k] > e[i,k] Then
Begin { new candidate is better }
choose := i;
k := noutfields;
End;
End;
End;
End;
End;
End; { getnextline }
Procedure init;
{ scan command line parameters }
Var temp : string;
ival : longint;
icod : integer;
i : byte;
Begin { init }
ninfiles := 0;
noutfields := 0;
outname := '';
For i := 1 To ParamCount Do
Begin { scan all parameters }
temp := ParamStr(i);
If temp = '?' Then usage;
If (Length(temp) <= 2) Or ((temp[1] <> '/') And (temp[1] <> '-')) Then
abort('Unknown command line switch ' + temp,2);
For icod := 1 To Length(temp) Do temp[icod] := UpCase(temp[icod]);
Case temp[2] Of
'F' : Begin { output field spec }
If noutfields >= maxoutfields Then
abort('Too many output fields specified',5);
If (temp[3] < 'A') Or (temp[3] > 'J') Then
abort('Unknown output field spec in '+ temp,3);
Inc(noutfields);
outfld[noutfields] := Ord(temp[3]) - 64;
If Length(temp) > 3 Then
Begin { get output field length }
{$R- } Val(Copy(temp,4,255),ival,icod);
{$IFDEF DEBUG } {$R+ } {$ENDIF }
If (icod <> 0) Or (Abs(ival) > 255) Then
abort('Illegal output field width in ' + temp,4);
outlen[noutfields] := ival;
End
Else outlen[noutfields] := 255;
End;
'I' : Begin { input file name }
If ninfiles >= maxinfiles Then
abort('Too many input files',6);
Inc(ninfiles);
If Pos('.',temp) = 0 Then temp := temp + '.IDX';
inname[ninfiles] := Copy(temp,3,255);
End;
'O' : Begin { output file name }
If outname <> '' Then
abort('More than one output file',7);
If Pos('.',temp) = 0 Then temp := temp + '.IDX';
outname := Copy(temp,3,255);
End;
'?', 'H' : usage; { help screen }
Else abort('Unknown command line switch ' + temp,2);
End;
End;
If noutfields = 0 Then abort('No output fields specified',8);
If ninfiles = 0 Then abort('No input files specified',9);
If outname = '' Then abort('No output file specified',10);
End; { init }
Procedure openfiles;
{ open all files, initialize buffers and records }
Var savfm, i : byte;
Begin { openfiles }
nopen := 0;
savfm := FileMode;
FileMode := 0;
For i := 1 To ninfiles Do
Begin { open all input files }
Assign(fin[i],inname[i]);
If MaxAvail > bufsize Then
Begin { set aside input buffer, if room available }
New(inbufptr[i]);
SetTextBuf(fin[i],inbufptr[i]^);
End;
Reset(fin[i]);
If IOResult <> 0 Then abort('Cannot open ' +inname[i]+ ' for input.',21);
ctin[i] := 0; { number of records read from this file }
e[i,1] := ''; { 'no current record from file i' }
eoff[i] := EoF(fin[i]); { eof status }
If Not eoff[i] Then Inc(nopen);
End;
FileMode := savfm;
Assign(fout,outname);
If MaxAvail > bufsize Then
Begin { set aside output buffer, if room available }
New(outbufptr);
SetTextBuf(fout,outbufptr^);
End;
Reset(fout);
If IOResult = 0 Then
Begin
write('Output file ',outname,' already exists. Continue? (y/n) ');
If Not yesnoq Then abort('Existing output file not overwritten.',23);
Close(fout);
End;
Rewrite(fout);
If IOResult <> 0 Then abort('Cannot open ' + outname + ' for output.',22);
ctout := 0;
End; { openfiles }
Begin { main }
writeln(progname,' ',version,' - ',copyright);
writeln;
writeln('Entia non sunt multiplicanda praeter necessitatem.');
writeln;
If ParamCount = 0 Then usage;
init;
openfiles;
While nopen > 0 Do
Begin { while there are records left, process them }
getnextline;
Inc(ctout);
If Lo(ctout) = 0 Then
Begin { consolate user }
write(#13,ctout);
For i := 1 To ninfiles Do write('/',ctin[i]);
End;
For i := 1 To Pred(noutfields) Do write(fout,e[choose,i],',');
writeln(fout,e[choose,noutfields]); { that did the trick }
If IOResult <> 0 Then abort('Error writing to ' + outname + ' - abort!',32);
e[choose,1] := ''; { mark this record 'done' }
End;
For i := 1 To ninfiles Do Close(fin[i]);
Close(fout);
write(#13,ctout);
For i := 1 To ninfiles Do write('/',ctin[i]);
writeln(' records processed.');
{ let DOS deallocate buffers }
End.